
jBGallery.Engine = function(el, data, options){

    //PRIVATE VARS
    var _current = options.current ? options.current + 1 : 1;//start 1 not 0
    var _slideshow = options.slideshow;//onLoadImage comanda
    var _interval = options.timers.interval;
    var _timer = false;
  var _observers = [];
  var _refresh = false;
  //var _timestamp = 0;
    //var _timergo = 1;
    
    var _target  = $('.jbgallery-target',el);
    var _loading = $(".jbg-loading", el);
                
    //PRIVATE METHODS
    function _preload(){
        _loading.css("opacity",0.5).show();
    }
    function _load(nr){
        options.before();
        
        _preload();
        _current = nr;
        
        //IE7
        var _i = data.get(_current - 1);
    var _pl = new Image();
        _pl.onload = function(){
      _target.fadeOut(options.timers.fade, function(){
        //http://code.google.com/p/chromium/issues/detail?id=7731
                if(this.src == _i.href)
            _i.href += '#' + new Date().getTime();
                $(this).hide().attr({//.hide()
                    "src" : _i.href , 
                    "alt" : _i.title
                });
            });
      
        };
    _pl.src = _i.href;
        
    }
    function _go(nr, ev){

    if(nr > data.length() || (nr === _current && !_refresh))
            return;
        if (_slideshow) {
            if(ev){
                _load(nr);
            }else{
                //clearTimeout(_timer); //BUG SLIDESHOW : 18/12/2010 
                _load(nr);//no event -> next, prev
            }
        } else {
            _load(nr);
        }
    _refresh = false;
    }
    function _right(ev){
    if(options.randomize == 2)
            _current = jBGallery.Randomizer(_current, data.length());

        if(_current < data.length()){
            var _goto = _current + 1;
        }else{
            var _goto = 1;
        }
        _go(_goto, ev);
    }
    function _left(){
        if(options.randomize == 2)
            _current = jBGallery.Randomizer(_current, data.length());

        if(_current > 1){
            var _goto = _current - 1;
        }else{
            var _goto = data.length();
        }
        _go(_goto);
    }
    function _play(){
        if(_slideshow)
            return;

        _slideshow = true;
        
        _right(_interval);//???
    }
    function _stop(){
        _slideshow = false;
        clearTimeout(_timer);
    }
    function _timeout(ev){
    clearTimeout(_timer); //BUG SLIDESHOW : 18/12/2010
        _timer = setTimeout(function(){
            _right(ev);
        }, _interval);
    }
  function _add(m, o){
        var _o = data[m](o);
        //se ho svuotato e aggiungo un elemento aggiorno il target
    if(data.length() == 1)
      _go(1);
        
    _notify(m, _o);
        options[m](_o);
  }
  function _push(o){
    //after empty
    _add('push', o);
  }
  function  _unshift(o){
        if(data.length() > 1)
            _current++;
        _add('unshift',o);
    }
  function  _pop(){
    data.pop();
    if (_current > data.length() && data.length() > 0) {
      _refresh = true;
      _go(data.length());
    }
    
        _notify('pop');
        options.pop();
        
    if (data.length() == 0)
            _empty();
  }
    function  _shift(){
        data.shift();
    if (_current == 1 && data.length() > 0) {
      _refresh = true;
      _go(1);
    } else {
      _current--;
    }
        _notify('shift');
        options.shift();

        if (data.length() == 0)
            _empty();
    }
    function  _empty(){
    _refresh = true;
    data.empty();
    _notify('empty');
        options.empty();
    }

  function _register(o){
    _observers.push(o);
  }
  function _notify(what, o){
    $.each(_observers, function(i,v){
      _observers[i].notify(what, o);
    });
  }
    //MAIN    
    
    //API
    return {
        current      : function(){
            return _current;
        },
        slideshow    : function(){
            return _slideshow;
        },
        length       : function(){
        return data.length();
      },
        play         : _play,
        stop         : _stop,
        go           : _go,
        right        : _right,
        left         : _left,
        target       : _target,
        loading      : _loading,
        timeout      : _timeout,
    //3.0
    register     : _register,
    push         : _push,
    shift        : _shift,
        pop          : _pop,
        unshift      : _unshift,
        empty        : _empty

    };
};